package com.eipv.multidatasource.component.init;

import com.eipv.multidatasource.component.cache.TableCache;
import com.eipv.multidatasource.component.config.migrate.TablePathConfig;
import com.eipv.multidatasource.component.task.PushMonitorTask;
import com.eipv.multidatasource.entity.Column;
import com.eipv.multidatasource.entity.Table;
import com.eipv.multidatasource.mapper.oracle.OracleTableMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

@Component
@Slf4j
public class InitCacheRunner implements CommandLineRunner {
    @Autowired
    private OracleTableMapper oracleTableMapper;
    @Autowired
    private TablePathConfig tablePathConfig;

    @Override
    public void run(String... args) throws IOException {
        long start = System.currentTimeMillis();
        List<Table> tables = oracleTableMapper.selectList(null);

        tables = filterTables(tables, tablePathConfig.getTablePath());

        //按照外键的顺序，将外键表排在前面
        sort(tables);

        OutputStream os = new FileOutputStream(new File("/BDC/table_list.txt"));
        for (Table t : tables) {
            os.write((t.getTableName() + "->" + t.getForeignTableName() + "\n").getBytes());
        }
        os.flush();
        os.close();
        TableCache.TABLES_OF_NEED_MIGRATE.addAll(tables);

        List<Table> copy = new ArrayList<Table>(TableCache.TABLES_OF_NEED_MIGRATE);

        copy.parallelStream().forEach(table -> {
            long count = oracleTableMapper.countData(table.getTableName());
            table.setCount(count);
            table.setHandled(0);
            table.setRowsOfRead(0);
            table.setRowsOfWrite(0);

            TableCache.TABLE_HANDLED.put(table.getTableName(), table);

            List<Column> columns = oracleTableMapper.selectColumnsByTable(table.getTableName());
            TableCache.saveColumns(table.getTableName(), columns);
        });
        long waste = System.currentTimeMillis() - start;

        log.info("初始化表数据完成,表个数:" + TableCache.TABLES_OF_NEED_MIGRATE.size() + ",耗时:" + waste);
        TableCache.INIT_FINISHED = true;

        new Thread(new PushMonitorTask()).start();
    }

    public static void sort(List<Table> tables) {
        List<Table> copy = new ArrayList<Table>(tables);
        AtomicBoolean switched = new AtomicBoolean(false);
        copy.parallelStream().forEach(c -> {
            if (c.getForeignTableName() != null) {
                int index = tables.indexOf(c);
                Table ftable = getTable(tables, c.getForeignTableName());
                int findex = tables.indexOf(ftable);
                if (index < findex) {
                    //交换
                    switched.set(true);
                    tables.set(index, ftable);
                    tables.set(findex, c);
                }
            }
        });
        if (switched.get()) {
            sort(tables);
        }
    }

    public static Table getTable(List<Table> tables, String tableName) {
        for (Table table : tables) {
            if (table.getTableName().equals(tableName)) {
                return table;
            }
        }
        return null;
    }

    public static List<Table> filterTables(List<Table> tables, String filePath) throws IOException {
        List<Table> newList = new ArrayList<Table>();

        BufferedReader reader = new BufferedReader(new FileReader(filePath));
        String tableName;
        while ((tableName = reader.readLine()) != null) {
            String finalTableName = tableName;
            tables.parallelStream().forEach(table -> {
                if (table.getTableName().equals(finalTableName)) {
                    newList.add(table);
                }
            });
        }
        return newList;

    }
}
